﻿using System;
using System.Linq;
using Helpers;
using MarriageFertility.Helpers;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Party.PartyComponents;
using TaleWorlds.CampaignSystem.Settlements;

namespace MarriageFertility.Actions
{
    public static class KingdomAction
    {
        public static void ChangeKingdomActionApply(
            Clan clan,  //家族
            Kingdom newKingdom,  //新王国
            ChangeKingdomAction.ChangeKingdomActionDetail detail,  //改变类型
            int awardMultiplier = 0, //奖励乘数
            bool byRebellion = false, //是否叛乱
            bool showNotification = true)  //展示信息
        {
            try
            {
                Kingdom oldKingdom = clan.Kingdom;
                clan.DebtToKingdom = 0;
                
                if (detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinKingdom ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinAsMercenary ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinKingdomByDefection)
                {
                    FactionHelper.AdjustFactionStancesForClanJoiningKingdom(clan, newKingdom);
                }
                
                if (detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinKingdom ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.CreateKingdom ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinKingdomByDefection)
                {
                    if (clan.IsUnderMercenaryService)
                        clan.EndMercenaryService(false);

                    if (oldKingdom != null)
                        clan.ClanLeaveKingdom(!byRebellion);

                    clan.Kingdom = newKingdom;

                    if (newKingdom != null && detail == ChangeKingdomAction.ChangeKingdomActionDetail.CreateKingdom)
                        ChangeRulingClanAction.Apply(newKingdom, clan);
                }
                
                else if (detail == ChangeKingdomAction.ChangeKingdomActionDetail.JoinAsMercenary)
                {
                    if (clan.IsUnderMercenaryService)
                        clan.EndMercenaryService(true);

                    clan.MercenaryAwardMultiplier = awardMultiplier;
                    clan.Kingdom = newKingdom;
                    clan.StartMercenaryService();

                    if (clan == Clan.PlayerClan)
                        Campaign.Current.KingdomManager.PlayerMercenaryServiceNextRenewDay = Campaign.CurrentTime + 720f;
                }
              
                else if (detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveWithRebellion ||
                         detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveKingdom ||
                         detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveAsMercenary ||
                         detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveByClanDestruction ||
                         detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveByKingdomDestruction)
                {
                    clan.Kingdom = null;

                    if (clan.IsUnderMercenaryService)
                        clan.EndMercenaryService(true);

                    switch (detail)
                    {
                        case ChangeKingdomAction.ChangeKingdomActionDetail.LeaveKingdom:
                            if (clan == Clan.PlayerClan && !clan.IsEliminated)
                            {
                                foreach (Clan otherClan in oldKingdom.Clans)
                                    ChangeRelationAction.ApplyRelationChangeBetweenHeroes(clan.Leader, otherClan.Leader, -20);
                            }

                            if (oldKingdom?.Leader == null)
                                return;

                            foreach (Settlement settlement in clan.Settlements.ToList())
                            {
                                ChangeOwnerOfSettlementAction.ApplyByLeaveFaction(oldKingdom.Leader, settlement);

                                foreach (Hero hero in settlement.HeroesWithoutParty.ToList())
                                {
                                    if (hero.CurrentSettlement != null && hero.Clan == clan)
                                    {
                                        if (hero.PartyBelongedTo != null)
                                        {
                                            LeaveSettlementAction.ApplyForParty(hero.PartyBelongedTo);
                                            EnterSettlementAction.ApplyForParty(hero.PartyBelongedTo, clan.Leader.HomeSettlement);
                                        }
                                        else
                                        {
                                            LeaveSettlementAction.ApplyForCharacterOnly(hero);
                                            EnterSettlementAction.ApplyForCharacterOnly(hero, clan.Leader.HomeSettlement);
                                        }
                                    }
                                }
                            }
                            break;

                        case ChangeKingdomAction.ChangeKingdomActionDetail.LeaveWithRebellion:
                            if (clan == Clan.PlayerClan)
                            {
                                foreach (Clan otherClan in oldKingdom.Clans)
                                    ChangeRelationAction.ApplyRelationChangeBetweenHeroes(clan.Leader, otherClan.Leader, -40);

                                DeclareWarAction.ApplyByRebellion(oldKingdom, clan);
                            }
                            break;

                        case ChangeKingdomAction.ChangeKingdomActionDetail.LeaveByKingdomDestruction:
                            foreach (StanceLink stance in oldKingdom.Stances.ToList())
                            {
                                if (stance.IsAtWar && !stance.IsAtConstantWar)
                                {
                                    IFaction enemyFaction = stance.Faction1 == oldKingdom ? stance.Faction2 : stance.Faction1;

                                    if (enemyFaction != clan && !clan.GetStanceWith(enemyFaction).IsAtWar)
                                        DeclareWarAction.ApplyByDefault(clan, enemyFaction);
                                }
                            }
                            break;
                    }
                }
                
                if (detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveAsMercenary ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveKingdom ||
                    detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveWithRebellion)
                {
                    foreach (StanceLink stanceLink in clan.Stances.ToList())
                    {
                        if (stanceLink.IsAtWar && !stanceLink.IsAtConstantWar)
                        {
                            IFaction opposingFaction = stanceLink.Faction1 == clan ? stanceLink.Faction2 : stanceLink.Faction1;
                            bool shouldSkipPeace = detail == ChangeKingdomAction.ChangeKingdomActionDetail.LeaveWithRebellion &&
                                                   clan == Clan.PlayerClan &&
                                                   opposingFaction == oldKingdom;

                            if (!shouldSkipPeace)
                            {
                                MakePeaceAction.Apply(clan, opposingFaction);
                                FactionHelper.FinishAllRelatedHostileActionsOfFactionToFaction(clan, opposingFaction);
                                FactionHelper.FinishAllRelatedHostileActionsOfFactionToFaction(opposingFaction, clan);
                            }
                        }
                    }

                    CheckIfPartyIconIsDirty(clan, oldKingdom);
                }
                
                foreach (WarPartyComponent warPartyComponent in clan.WarPartyComponents)
                {
                    if (warPartyComponent.MobileParty.MapEvent == null)
                        warPartyComponent.MobileParty.Ai.SetMoveModeHold();
                }
                
                CampaignEventDispatcher.Instance.OnClanChangedKingdom(clan, oldKingdom, newKingdom, detail, showNotification);
            }
            catch (Exception e)
            {
                Log.ErrorMessage(e.StackTrace);
                Log.ErrorMessage(e.Message);
            }
        }

        private static void CheckIfPartyIconIsDirty(Clan clan, Kingdom oldKingdom)
        {
            IFaction newFaction = clan.Kingdom ?? (IFaction)clan;
            IFaction oldFaction = oldKingdom != null ? oldKingdom : clan;

            foreach (MobileParty mobileParty in MobileParty.All)
            {
                if (mobileParty.IsVisible &&
                    (mobileParty.Party.Owner?.Clan == clan ||
                     (clan == Clan.PlayerClan &&
                      ((!FactionManager.IsAtWarAgainstFaction(mobileParty.MapFaction, newFaction) &&
                        FactionManager.IsAtWarAgainstFaction(mobileParty.MapFaction, oldFaction)) ||
                       (FactionManager.IsAtWarAgainstFaction(mobileParty.MapFaction, newFaction) &&
                        !FactionManager.IsAtWarAgainstFaction(mobileParty.MapFaction, oldFaction))))))
                {
                    mobileParty.Party.SetVisualAsDirty();
                }
            }

            foreach (Settlement settlement in clan.Settlements)
                settlement.Party.SetVisualAsDirty();
        }
    }
}
